#
#@author devdoer@gmail.com
#
import urlparse
from anole import AnoleError
#AnoleError=Exception
class InvalidURL(AnoleError):
	#maybe from Exception is better, for it is a utility
	def __init__(self,msg,url):
		self.args=(msg,url)
URLError=InvalidURL		
		

def url_split(strURL):
	#strURL=schema://host/path?query#frag
	#host=host(:port)
	idx=strURL.find('://')
	if idx==-1:return None
	schema=strURL[0:idx]
	idx2=strURL.find('/',idx+3)
	if idx2==-1:
		host=strURL[idx+3:]
		return (schema,host,'','','')
		#return (schema,host,'/','','')
	host=strURL[idx+3:idx2]
	idx3=strURL.find('?',idx2)
	if idx3==-1:
		idx4=strURL.find('#',idx2)
		if idx4==-1:
		#strURL=schema://host/path
			path=strURL[idx2:]
			return (schema,host,path,'','')
		else:
		#strURL=schema://host/path#frag
			path=strURL[idx2:idx4]
			frag=strURL[idx4+1:]
			return (schema,host,path,'',frag)
	else:
		path=strURL[idx2:idx3]
		idx4=strURL.find('#',idx3)
		if idx4==-1:
		#strURL=schema://host/path?query
			query=strURL[idx3+1:]
			return (schema,host,path,query,'')
		else:
		#strURL=schema://host/path?query#frag
			query=strURL[idx3+1:idx4]
			frag=strURL[idx4+1:]
			return (schema,host,path,query,frag)

	

def _get_type(path):
	idx=path.rfind('.')
	if idx==-1:
		fileType=''
	else:
		ext=path[idx+1:]
		idx=ext.find('/')
		if idx!=-1:
			#/x.php/avbc
			fileType=ext[:idx]
		else:	
			fileType=ext
	return fileType
def url_file_type(strURL):
	t=url_split(strURL)
	path=t[2]
	return _get_type(path)	
	
	
SESSION_KEY=('sid','session','sessid','sesid')
PORT_MAP={
		'http':80,
		'https':443,
		'ftp':21,
}
class URL:
	
	def __init__(self,url,baseURL=''):
		
		#t=self.parse(url,baseURL)
		if baseURL:
			self.__fullURL=urlparse.urljoin(baseURL,url)
		else :
			self.__fullURL=url
		self.__fullURL=self.__fullURL.strip().lower()	
		self.__fullURLSeg=url_split(self.__fullURL)
		if not self.__fullURLSeg:
			raise InvalidURL('invalid url format',self.__fullURL)
		if not self.__fullURLSeg[0]:
			raise InvalidURL('no protocol defined',self.__fullURL)
		
		else:
			self.__protocol=self.__fullURLSeg[0]
		if not self.__fullURLSeg[1]:
			raise InvalidURL('no host defined',self.__fullURL)
		else:
			self.__host=self.__fullURLSeg[1]
			idx=self.__host.find(':')
			if idx!=-1 :
				idx2=self.__host.find('@',idx)
				if idx2!=-1:
				#such as  user:pass@host
					idx=self.__host.find(':',idx2)
			if idx==-1:
				try:
					self.__port=PORT_MAP[self.__protocol]
				except KeyError:	
					self.__port=0
			else:
				try:
					self.__port=int(self.__host[idx+1:])
					self.__host=self.__host[:idx]
				except ValueError:
					raise InvalidURL('port number is invalid',self.__fullURL)
	
		if not self.__fullURLSeg[2]:
			#http://www.sina.com.cn
			#print 'x'
			self.__path_to_file='/'
			self.__fullURL+='/'
		elif not self.__fullURLSeg[3]:
			#http://www.sina.com.cn/
			#http://www.sina.com.cn/file/
			#http://www.sina.com.cn/file.html
			#http://www.sina.com.cn/file?
			#print 'y'
			self.__path_to_file=self.__fullURLSeg[2]
		else:
			#http://www.sina.com.cn/file/query?x=3
			#http://www.sina.com.cn/file/query?x
			#http://www.sina.com.cn/file/query?x=3/file/file.html
			#print 'z'
			self.__path_to_file=self.__fullURLSeg[2]+'?'+self.__fullURLSeg[3]
		self.__depth=self.__path_to_file.count('/')
		self.__fileType=_get_type(self.__path_to_file)
		self.__fragment=self.__fullURLSeg[4]	
	def get_clean_session(self,withFrag=False):
		query=self.__fullURLSeg[3]
		if not query:
			return self.full_url(withFrag)
		for s in SESSION_KEY:
			if query.find(s)!=-1:
			#got session sigificance	
				l=[]
				qs=query.split('&')
				for q in qs:
					if q.find(s)!=-1 and len(q)>=20:
					#session id 	
						continue
					l.append(q)
				query='&'.join(l)		
		if  withFrag and self.__fullURLSeg[3]:		
			return self.__fullURLSeg[0]+'://'+self.__fullURLSeg[1]+self.__fullURLSeg[2]+'?'+query+'#'+self.__fullURLSeg[4]		
		else:
			return self.__fullURLSeg[0]+'://'+self.__fullURLSeg[1]+self.__fullURLSeg[2]+'?'+query		


		
	def full_url(self,withFrag=False):
		if withFrag:
			return self.__fullURL
		else:
			return urlparse.urldefrag(self.__fullURL)[0]
	def path_to_file(self):
		return self.__path_to_file
	def host(self):
		return self.__host
	def port(self):
		return self.__port
	def protocol(self):
		return self.__protocol
	def depth(self):
		return self.__depth
	def file_type(self):
		return self.__fileType

def test():
	u1=URL('/www.sohu.com/file/','http://sina.com.cn')
	u2=URL('http://www.sohu.com/file/')
	u3=URL('http://www.sohu.com')
	u4=URL('/www.sohu.com/file/?','http://sina.com.cn')
	u5=URL('/www.sohu.com/file/?x=5','http://sina.com.cn')
	u6=URL('/www.sohu.com/file/?x=5/file.html','http://sina.com.cn')
	u7=URL('http://www.sohu.com:8080/xxx.jpg')
	u8=URL('http://www.sohu.com/base#hello?page=3','http://www.sina.com.cn/index.html')
	L=[u1,u2,u3,u4,u5,u6,u7,u8]
	for u ,i in zip(L,xrange(len(L))):
		
		
		print '------------------------------------------------'
		print i
		print u.full_url()
		print u.path_to_file()
		print u.host()
		print u.port()
		print u.depth()
		print u.file_type()
def test2():
	try:
		u=URL('www.sohu.com')
	except InvalidURL,e:
		print e
	try:
		u=URL('s://www.sohu.com:8434')
	except InvalidURL,e:
		print e
	try:
		u=URL('rtsp://www.sohu.com')
	except InvalidURL,e:
		print e
	try:
		u=URL('file','www.shou.com/')
	except InvalidURL,e:
		print e
if __name__=='__main__':
	test()
	#test2()
